﻿using Colorful;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MyConsole = Colorful.Console;

namespace Snake
{
    class Program
    {
        //移动方向
        enum Direction
        {
            TOP = 0,
            RIGHT = 1,
            BOTTOM = 2,
            LEFT = 3
        }

        static int _MENUINEDX;  //菜单序号 
        static int _MAPWIDTH;   //地图宽度
        static int _MAPHEIGHT;  //地图高度
        static int _LEVEL;      //运动速度等级  
        static Dictionary<int, int> _SPACE;//运动速度  

        static int _SCORE;      //分数
        static List<Location> _SNAKEBODYLEN;//起始位置  
        static Location _FOODLOCATION;//食物位置 
        static Location _NEWBODY;//新的身体位置
        static Direction _MOVEDIR;
        static string _BODYCHAR;//蛇的样式
        static string _FOODCHAR;//食物的样式
        static List<string> _STARTMENUITEMS;//开始菜单
        static List<string> _SETUPMENUITEMS;//设置菜单
        static Thread _RUN;


        static void Main(string[] args)
        {
            InitGame();//初始化游戏参数

            DrawStartUI();//初始化菜单


            MyConsole.Clear();
            System.Console.WriteLine("已经退出本程序！");
        }


        //判断菜单序号
        static void NextStep()
        {
            switch (_MENUINEDX)
            {
                case 0: //开始游戏
                    StartGame();
                    break;
                case 1: //设置界面
                    SetUp();
                    break;
                case 2: //记录

                    break;
                case 3: //退出

                    break;
            }
        }

        //开始
        static void StartGame()
        {
            System.Console.Clear();//清屏
            DrawFrame(_MAPWIDTH, _MAPHEIGHT, Color.Purple);//画地图
            InitFood();//初始化食物位置
            InitSnake();//初始化蛇的位置

            ConsoleKeyInfo key;
            while (true)
            {
                key = MyConsole.ReadKey(true);
                if (key.Key == ConsoleKey.W || key.Key == ConsoleKey.UpArrow)
                {
                    _MOVEDIR = Direction.TOP;
                    Alwary();
                }
                if (key.Key == ConsoleKey.S || key.Key == ConsoleKey.DownArrow)
                {
                    _MOVEDIR = Direction.BOTTOM;
                    Alwary();
                }
                if (key.Key == ConsoleKey.A || key.Key == ConsoleKey.LeftArrow)
                {
                    _MOVEDIR = Direction.LEFT;
                    Alwary();
                }
                if (key.Key == ConsoleKey.D || key.Key == ConsoleKey.RightArrow)
                {
                    _MOVEDIR = Direction.RIGHT;
                    Alwary();
                }
            }
        }

        //设置参数
        static void SetUp()
        {
            System.Console.Clear();//清屏
            _MENUINEDX = 0;
            ConsoleKeyInfo key;
            DrawMenuItem(_SETUPMENUITEMS, _MENUINEDX, new Location(10, 1), Color.LawnGreen);
            DrawMenuItem(new List<string>() { "[Enter]Confirm", "[Esc]Cancel" }, new Location(15, 5), Color.Red);
            ShowValue();
            while (true)
            {
                key = MyConsole.ReadKey(true);
                if (Tools.EqualsKey(key.Key, "UP"))
                {
                    if (_MENUINEDX > 0)
                    {
                        _MENUINEDX--;
                    }
                    else
                    {
                        _MENUINEDX = _SETUPMENUITEMS.Count - 1;
                    }
                }
                if (Tools.EqualsKey(key.Key, "DOWN"))
                {
                    if (_MENUINEDX < _SETUPMENUITEMS.Count - 1)
                    {
                        _MENUINEDX++;
                    }
                    else
                    {
                        _MENUINEDX = 0;
                    }
                }
                if (Tools.EqualsKey(key.Key, "LEFT"))
                {
                    ChangeValue("-");
                }
                if (Tools.EqualsKey(key.Key, "RIGHT"))
                {
                    ChangeValue("+");
                }
                if (Tools.EqualsKey(key.Key, "ENTER"))
                {
                    DrawStartUI();
                    return;
                }
                if (Tools.EqualsKey(key.Key, "ESC"))
                {
                    _MENUINEDX = 0;
                    _MAPWIDTH = 50;
                    _MAPHEIGHT = 10;
                    _LEVEL = 1;
                    DrawStartUI();
                    return;
                }
                DrawMenuItem(_SETUPMENUITEMS, _MENUINEDX, new Location(10, 1), Color.LawnGreen);
                ShowValue();
            }

        }

        //显示对应的值
        static void ShowValue()
        {
            List<string> list = new List<string>() { _MAPWIDTH.ToString(), _MAPHEIGHT.ToString(), _LEVEL.ToString() };
            DrawMenuItem(list, _MENUINEDX, new Location(50, 1), Color.GreenYellow);
        }

        //变化值
        static void ChangeValue(string op)
        {
            if (_MENUINEDX == 0)
            {
                if (op == "-")
                {
                    if (_MAPWIDTH > 50)
                    {
                        _MAPWIDTH--;
                    }
                    else
                    {
                        _MAPWIDTH = 100;
                    }
                }
                if (op == "+")
                {
                    if (_MAPWIDTH < 100)
                    {
                        _MAPWIDTH++;
                    }
                    else
                    {
                        _MAPWIDTH = 50;
                    }
                }
            }
            if (_MENUINEDX == 1)
            {
                if (op == "-")
                {
                    if (_MAPHEIGHT > 10)
                    {
                        _MAPHEIGHT--;
                    }
                    else
                    {
                        _MAPHEIGHT = 20;
                    }
                }
                if (op == "+")
                {
                    if (_MAPHEIGHT < 20)
                    {
                        _MAPHEIGHT++;
                    }
                    else
                    {
                        _MAPHEIGHT = 10;
                    }
                }
            }
            if (_MENUINEDX == 2)
            {
                if (op == "-")
                {
                    if (_LEVEL > 1)
                    {
                        _LEVEL--;
                    }
                    else
                    {
                        _LEVEL = 5;
                    }
                }
                if (op == "+")
                {
                    if (_LEVEL < 5)
                    {
                        _LEVEL++;
                    }
                    else
                    {
                        _LEVEL = 1;
                    }
                }
            }
        }


        #region 初始化
        //初始化游戏
        static void InitGame()
        {
            _SPACE = new Dictionary<int, int>();//难度等级对照字典
            _SPACE.Add(1, 500);
            _SPACE.Add(2, 400);
            _SPACE.Add(3, 300);
            _SPACE.Add(4, 250);
            _SPACE.Add(5, 200);
            _STARTMENUITEMS = new List<string>() { "Start", "SetUp", "Record", "Exit" };
            _SETUPMENUITEMS = new List<string>() { "Map Width[50-100]", "Map Height[10-20]", "Degree[1-5]" };

            _MENUINEDX = 0;//菜单序号
            _MAPWIDTH = 50;//地图宽度
            _MAPHEIGHT = 10;//地图高度
            _LEVEL = 1;//难度等级 
            _SCORE = 0;//分数
            _SNAKEBODYLEN = new List<Location>() { new Location() { X = 3, Y = 3 } };//蛇身初始位置
            _FOODLOCATION = new Location();//食物的位置
            _NEWBODY = new Location();//新身体的位置
            _BODYCHAR = "*";//蛇身子的样式
            _FOODCHAR = "@";//食物的样式
        }

        //初始化食物
        static void InitFood()
        {
            Random r = new Random();
            int X = r.Next(2, _MAPWIDTH - 1);
            int Y = r.Next(2, _MAPHEIGHT - 1);

            foreach (Location item in _SNAKEBODYLEN)
            {
                if (X == item.X)
                {
                    if (Y == item.Y)
                    {
                        InitFood();
                    }
                }
            }


            System.Console.SetCursorPosition(X, Y);
            _FOODLOCATION.X = X;
            _FOODLOCATION.Y = Y;
            MyConsole.WriteLine(_FOODCHAR, Color.Yellow);
            System.Console.SetCursorPosition(0, 20);
            TESTSHOWLOCATION();
        }

        //初始化蛇的位置
        static void InitSnake()
        {
            foreach (Location item in _SNAKEBODYLEN)
            {
                System.Console.SetCursorPosition(item.X, item.Y);
                MyConsole.Write(_BODYCHAR, Color.Wheat);
            }
        }
        #endregion


        #region 绘制页面
        //绘制开始界面
        static void DrawStartUI()
        {
            System.Console.SetCursorPosition(0, 0);
            Figlet fig = new Figlet(FigletFont.Load("starwars.flf"));
            MyConsole.WriteLine(fig.ToAscii("snake"), Color.Olive);
            System.Console.SetCursorPosition(0, 6);
            DrawFrame(55, 8, Color.Orchid);
            DrawMenuItem(_STARTMENUITEMS, _MENUINEDX, new Location(20, 8), Color.Orange);
            ConsoleKeyInfo key;
            while (true)
            {
                key = MyConsole.ReadKey(true);

                if (Tools.EqualsKey(key.Key, "UP"))
                {
                    if (_MENUINEDX > 0)
                    {
                        _MENUINEDX--;
                    }
                    else
                    {
                        _MENUINEDX = _STARTMENUITEMS.Count - 1;
                    }
                }
                else if (Tools.EqualsKey(key.Key, "DOWN"))
                {
                    if (_MENUINEDX < _STARTMENUITEMS.Count - 1)
                    {
                        _MENUINEDX++;
                    }
                    else
                    {
                        _MENUINEDX = 0;
                    }
                }
                else if (Tools.EqualsKey(key.Key, "ENTER"))
                {
                    NextStep();//根据菜单序号进入不同模块
                    if (_MENUINEDX == 3)
                    {
                        return;
                    }
                }
                DrawMenuItem(_STARTMENUITEMS, _MENUINEDX, new Location(20, 8), Color.Orange);
            }

        }

        //绘制框
        static void DrawFrame(int width, int height, Color mapColor)
        {
            for (int i = 0; i < height; i++)
            {
                if (i == 0 || i == height - 1)
                {
                    for (int j = 0; j < width; j++)
                    {
                        if (j < width - 1)
                        {
                            MyConsole.Write("*", mapColor);
                        }
                        else
                        {
                            MyConsole.WriteLine("*", mapColor);
                        }
                    }
                }
                else
                {
                    MyConsole.Write("*", mapColor);
                    for (int j = 0; j < width - 2; j++)
                    {
                        MyConsole.Write(" ");
                    }
                    MyConsole.WriteLine("*", mapColor);
                }
            }
        }

        //绘制菜单条目的函数
        static void DrawMenuItem(List<string> items, int index, Location loc, Color color)
        {
            MyConsole.SetCursorPosition(loc.X, loc.Y);
            for (int i = 0; i < items.Count; i++)
            {
                MyConsole.SetCursorPosition(loc.X, loc.Y + i);
                if (i == index)
                {
                    MyConsole.WriteLine("●" + items[i] + "    ", color);
                }
                else
                {
                    MyConsole.WriteLine(" " + items[i] + "    ");
                }
            }
        }

        static void DrawMenuItem(List<string> items, Location loc, Color color)
        {
            MyConsole.SetCursorPosition(loc.X, loc.Y);
            for (int i = 0; i < items.Count; i++)
            {
                MyConsole.SetCursorPosition(loc.X + (i * 20), loc.Y);
                MyConsole.Write("" + items[i] + "    ", color);
            }
        }

        #endregion


        #region 进行时
        //一直运动的小方法
        static void Alwary()
        {
            if (_RUN == null)
            {
                _RUN = new Thread(AlwaysMove);
            }
            if (_RUN.ThreadState == ThreadState.Unstarted)
            {
                _RUN.Start();
            }
            else
            {
                _RUN.Abort();
                _RUN = new Thread(AlwaysMove);
                _RUN.Start();
            }
        }

        //长身体
        static void AddBody()
        {
            if (_SNAKEBODYLEN[0].X == _FOODLOCATION.X && _SNAKEBODYLEN[0].Y == _FOODLOCATION.Y)
            {
                _SNAKEBODYLEN.Add(new Location() { X = _NEWBODY.X, Y = _NEWBODY.Y });
                _SCORE++;
                InitFood();
            }
        }

        //一直运动（设置速度
        static void AlwaysMove()
        {
            while (true)
            {
                Thread.Sleep(_SPACE[_LEVEL]);
                Move(_MOVEDIR);
            }
        }

        //显示分数
        static void AddScore()
        {
            System.Console.SetCursorPosition(0, _MAPHEIGHT + 1);
            MyConsole.WriteLine("You Now Score:" + _SCORE, Color.Pink);
        }

        //移动
        static void Move(Direction moveDir)
        {
            AddScore();
            foreach (Location item in _SNAKEBODYLEN)
            {
                System.Console.SetCursorPosition(item.X, item.Y);
                MyConsole.Write(" ");
            }
            for (int i = _SNAKEBODYLEN.Count - 1; i >= 0; i--)
            {
                if (i == 0)
                {
                    switch (moveDir)
                    {
                        case Direction.TOP:
                            _SNAKEBODYLEN[i].Y = _SNAKEBODYLEN[i].Y - 1;//TOP
                            if (_SNAKEBODYLEN[i].Y < 1)
                            {
                                OverGame();
                            }
                            break;
                        case Direction.BOTTOM:
                            _SNAKEBODYLEN[i].Y = _SNAKEBODYLEN[i].Y + 1;//BOTTOM
                            if (_SNAKEBODYLEN[i].Y >= _MAPHEIGHT - 1)
                            {
                                OverGame();
                            }
                            break;
                        case Direction.LEFT:
                            _SNAKEBODYLEN[i].X = _SNAKEBODYLEN[i].X - 1;//LEFT
                            if (_SNAKEBODYLEN[i].X < 1)
                            {
                                OverGame();
                            }
                            break;
                        case Direction.RIGHT:
                            _SNAKEBODYLEN[i].X = _SNAKEBODYLEN[i].X + 1;//RIGHT
                            if (_SNAKEBODYLEN[i].X >= _MAPWIDTH - 1)
                            {
                                OverGame();
                            }
                            break;
                    }
                }
                else
                {
                    if (i == _SNAKEBODYLEN.Count - 1)
                    {
                        _NEWBODY.X = _SNAKEBODYLEN[i].X;
                        _NEWBODY.Y = _SNAKEBODYLEN[i].Y;
                    }
                    _SNAKEBODYLEN[i].X = _SNAKEBODYLEN[i - 1].X;
                    _SNAKEBODYLEN[i].Y = _SNAKEBODYLEN[i - 1].Y;
                }
            }
            //显示
            foreach (Location item in _SNAKEBODYLEN)
            {
                System.Console.SetCursorPosition(item.X, item.Y);
                MyConsole.Write(_BODYCHAR, Color.Wheat);
            }
            TESTSHOWLOCATION();
            AddBody();

        }
        #endregion


        //设置参数
        static void SetUpParame()
        {
            while (true)
            {
                MyConsole.Write("请输入地图的宽度（50-200）：");
                string inputWidth = System.Console.ReadLine();
                if (int.TryParse(inputWidth, out  _MAPWIDTH))
                {
                    if (_MAPWIDTH >= 50 && _MAPWIDTH <= 200)
                    {
                        while (true)
                        {
                            MyConsole.Write("请输入地图的高度（10-20）：");
                            string inputHeight = System.Console.ReadLine();
                            if (int.TryParse(inputHeight, out _MAPHEIGHT))
                            {
                                if (_MAPHEIGHT >= 10 && _MAPHEIGHT <= 20)
                                {

                                    while (true)
                                    {
                                        MyConsole.Write("请选择难度（1-5）：");
                                        string inputDegree = System.Console.ReadLine();
                                        switch (inputDegree)
                                        {
                                            //case "1": _SPACE = 500; break;
                                            //case "2": _SPACE = 300; break;
                                            //case "3": _SPACE = 250; break;
                                            //case "4": _SPACE = 200; break;
                                            //case "5": _SPACE = 100; break;
                                            default: MyConsole.WriteLine("请输入1-5之间的数字！", Color.Red); break;
                                        }
                                        break;
                                    }
                                    break;
                                }
                                else
                                {
                                    MyConsole.WriteLine("请输入10-20之间的数字！", Color.Red);
                                }
                            }
                            else
                            {
                                MyConsole.WriteLine("请输入数字！", Color.Red);
                            }
                        }
                        break;

                    }
                    else
                    {
                        MyConsole.WriteLine("请输入50-200之间的数字！", Color.Red);
                    }
                }
                else
                {
                    MyConsole.WriteLine("请输入数字！", Color.Red);
                }
            }
            System.Console.Clear();
        }







        //GAME OVER
        static void OverGame()
        {
            System.Console.Clear();
            System.Console.SetCursorPosition(0, 0);
            string str = "GAME OVER";
            Figlet fig = new Figlet(FigletFont.Load("starwars.flf"));
            MyConsole.Write(fig.ToAscii(str), Color.Olive);

            DrawMenuItem(new List<string>() { "[Enter]重新开始", "[Esc]退出" }, new Location(6, 7), Color.Wheat);
            ConsoleKeyInfo key;
            while (true)
            {
                key = MyConsole.ReadKey(true);
                if (Tools.EqualsKey(key.Key, "ENTER"))
                {
                    MyConsole.Clear();
                    InitGame();
                    DrawStartUI();
                }
                if (Tools.EqualsKey(key.Key, "ESC"))
                {
                    return;
                }
            }
        }



        //（测试）显示food位置和head位置
        static void TESTSHOWLOCATION()
        {
            System.Console.SetCursorPosition(_MAPWIDTH + 2, 0);
            MyConsole.WriteLine(string.Format("HEAD:({0},{1})", _SNAKEBODYLEN[0].X, _SNAKEBODYLEN[0].Y), Color.Tomato);
            System.Console.SetCursorPosition(_MAPWIDTH + 2, 1);
            MyConsole.WriteLine(string.Format("FOOD:({0},{1})", _FOODLOCATION.X, _FOODLOCATION.Y), Color.Tomato);

        }
    }
}
